package com.hsh.erp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hsh.erp.constants.ResultConstants;
import com.hsh.erp.domain.common.Result;
import com.hsh.erp.domain.dto.OrderDTO;
import com.hsh.erp.domain.entity.Order;
import com.hsh.erp.domain.vo.OrderVO;
import com.hsh.erp.domain.vo.OutboundVO;
import com.hsh.erp.enums.InOutTypeEnum;
import com.hsh.erp.mapper.OrderMapper;
import com.hsh.erp.service.*;
import com.hsh.erp.utils.DataUtils;
import com.hsh.erp.utils.MyBeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;


/**
 * @author USER
 * @description 针对表【order】的数据库操作Service实现
 * @createDate 2024-05-30 16:21:43
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Resource
    private OrderMapper orderMapper;
    @Resource
    @Lazy
    private ShopService shopService;
    @Resource
    @Lazy
    private RepositoryService repositoryService;
    @Resource
    @Lazy
    private ProductService productService;

    @Resource
    @Lazy
    private OutboundService outboundService;

    /**
     * 列表查询
     *
     * @param orderVO
     * @return
     */
    @Override
    public Result<List<OrderDTO>> getList(OrderVO orderVO) {
        List<OrderDTO> orderDTOList = orderMapper.getOrderDTOList(orderVO);

        // 获取供应商名称，仓库名称，产品名称
        for (OrderDTO orderDTO : orderDTOList) {
            orderDTO.setShopName(shopService.getNameById(orderDTO.getShopId()))
                    .setRepositoryName(repositoryService.getNameById(orderDTO.getRepositoryId()))
                    .setProductName(productService.getNameById(orderDTO.getProductId()));
        }
        return Result.success(orderDTOList);
    }

    /**
     * 修改一条记录
     *
     * @param orderVO
     * @return
     */
    @Override
    public Result updateOne(OrderVO orderVO) {
        // 初始化修改参数
        orderVO.updateInit();

        // 查找要修改的记录
        Order oldOrder = getById(orderVO.getId());

        // 修改是否成功
        boolean update;
        // 是否修改了no，productId，repositoryId
        boolean isUpdateNo = oldOrder.getNo().equals(orderVO.getNo()) && oldOrder.getProductId().equals(orderVO.getProductId())
                && oldOrder.getRepositoryId().equals(orderVO.getRepositoryId());
        // 是否修改了actualNum
        boolean isUpdateNum = oldOrder.getActualNum().equals(orderVO.getActualNum());

        // 未修改no，productId，repositoryId，actualNum，直接修改订单
        if (isUpdateNo && isUpdateNum) {
            update = updateById(MyBeanUtils.copy(orderVO, Order.class));
            return Result.create(update);
        }

        // no 或 productId 或 repositoryId 未修改，修改了发货数量
        if (isUpdateNo && !isUpdateNum) {
            update = updateOrderNum(oldOrder, orderVO);
            return Result.create(update);
        }

        // 修改了no 或 productId 或 repositoryId
        update = updateOrder(oldOrder, orderVO);
        return Result.create(update);
    }

    /**
     * no 或 productId 或 repositoryId 未修改，但修改了num
     * 修改订单,新增出库
     *
     * @param oldOrder
     * @param orderVO
     * @return
     */
    @Transactional
    public boolean updateOrderNum(Order oldOrder, OrderVO orderVO) {
        // 修改订单
        boolean updateOrder = updateById(MyBeanUtils.copy(orderVO, Order.class));

        // 新增出库
        OutboundVO outboundVO = MyBeanUtils.copy(orderVO, OutboundVO.class)
                .setId(null)
                .setActualNum(orderVO.getActualNum() - oldOrder.getActualNum())
                .setTypeId(InOutTypeEnum.UPDATE_ORDER_OUT.getId());
        boolean updateOutbound = outboundService.addOne(outboundVO).isSuccess();

        return updateOrder && updateOutbound;
    }

    /**
     * 修改了no 或 productId 或 repositoryId
     * 删除 旧订单，旧出库
     * 新增 新订单，新出库
     *
     * @param oldOrder
     * @param orderVO
     * @return
     */
    @Transactional
    public boolean updateOrder(Order oldOrder, OrderVO orderVO) {
        // 删除旧订单
        OrderVO deleteOrderVO = MyBeanUtils.copy(oldOrder, OrderVO.class)
                .setIsDelete(1)
                .setNote(ResultConstants.UPDATE_ORDER_TO_DELETE);
        boolean delete = deleteOne(deleteOrderVO).isSuccess();

        // 新增新订单
        orderVO.setId(null)
                .setIsForcedMerger(1)
                .setIsAddNum(1)
                .setNote(ResultConstants.UPDATE_ORDER_TO_ADD)
                .setCreateTime(LocalDateTime.now());
        boolean add = addOne(orderVO).isSuccess();

        return delete && add;
    }


    /**
     * 删除一条记录
     *
     * @param orderVO
     * @return
     */
    @Override
    public Result deleteOne(OrderVO orderVO) {
        // 找到要删除的记录
        Order oldOrder = getById(orderVO.getId());
        if (oldOrder == null) {
            return Result.fail();
        }
        // 删除状态无改动，无需改变
        if (oldOrder.getIsDelete().equals(orderVO.getIsDelete())) {
            return Result.success();
        }
        boolean delete;
        // 删除（恢复） 订单，同时更正 出库记录 和 库存
        if (orderVO.getIsDelete() == 0) {
            // 恢复订单 已删除->未删除
            delete = recoverOrder(oldOrder, orderVO);
        } else {
            // 删除订单 未删除->已删除
            delete = deleteOrder(oldOrder, orderVO);
        }
        return Result.create(delete);
    }


    /**
     * 新增一条记录
     *
     * @param orderVO
     * @return
     */
    @Override
    @Transactional
    public Result addOne(OrderVO orderVO) {

        boolean save = false;

        Order oldOrder = getOneByQuery(orderVO);
        // 数据初始化
        orderVO.addInit();
        // no+productId+repositoryId 不存在，直接添加，并新增出库
        if (oldOrder == null) {
            return Result.create(addOrder(orderVO));
        }

        // no+productId+repositoryId 已存在，且 expressNum 非空且已存在，订单重复导入，无需操作
        if (orderVO.getIsForcedMerger() == 0 && DataUtils.isIncludeEquals(oldOrder.getExpressNum(), orderVO.getExpressNum())) {
            log.info("订单{}重复导入：{}", orderVO.getNo(), orderVO);
            return Result.fail("订单重复导入");
        }

        // no+productId+repositoryId 已存在，状态为已删除，恢复旧订单
        if (oldOrder.getIsDelete() != 0) {
            orderVO.setId(oldOrder.getId());
            save = recoverOrder(MyBeanUtils.copy(orderVO, Order.class), orderVO);
            return Result.create(save);
        }

        // no+productId+repositoryId 已存在，且 expressNum 不重复 拼接快递单号
        save = reissueOrder(oldOrder, orderVO);

        return Result.create(save);

    }


    /**
     * 批量新增记录
     *
     * @param orderVOList
     * @return
     */
    @Override
    public Result addList(List<OrderVO> orderVOList) {
        int addNum = 0;
        for (OrderVO orderVO : orderVOList) {
            addNum = addOne(orderVO).isSuccess() ? ++addNum : addNum;
        }
        return Result.create(addNum, orderVOList.size() - addNum);
    }


    /**
     * 根据 no+product_id+repository_id,
     * 查找 未删除 的记录
     *
     * @param orderVO
     * @return
     */
    @Override
    public Order getOneByQuery(OrderVO orderVO) {
        QueryWrapper<Order> queryWrapper = new QueryWrapper<Order>()
                .eq("no", orderVO.getNo())
                .eq("product_id", orderVO.getProductId())
                .eq("repository_id", orderVO.getRepositoryId());

        return getOne(queryWrapper);
    }


    /**
     * 删除订单，同时删除出库记录
     *
     * @param oldOrder 数据库要删除的订单
     * @param orderVO  要删除的内容，is_delete,note
     * @return
     */
    @Transactional
    public boolean deleteOrder(Order oldOrder, OrderVO orderVO) {
        oldOrder.setNote(orderVO.getNote()).setIsDelete(orderVO.getIsDelete());
        // 删除订单
        boolean deleteOrder = updateById(oldOrder);
        // 删除出库记录
        boolean deleteOutbound = outboundService.deleteByOrder(oldOrder);

        return deleteOrder && deleteOutbound;
    }

    /**
     * 恢复订单，同时新增一条出库记录
     *
     * @param oldOrder 数据库要删除的订单
     * @param orderVO  要删除的内容，is_delete,note
     * @return
     */
    @Transactional
    public boolean recoverOrder(Order oldOrder, OrderVO orderVO) {
        oldOrder.setNote(orderVO.getNote()).setIsDelete(orderVO.getIsDelete());
        // 恢复订单
        boolean deleteOrder = updateById(oldOrder);
        // 新增出库记录
        OutboundVO outboundVO = MyBeanUtils.copy(oldOrder, OutboundVO.class)
                .setId(null)
                .setTypeId(InOutTypeEnum.UPDATE_ORDER_OUT.getId())
                .setCreateTime(LocalDateTime.now());

        boolean deleteOutbound = outboundService.addOne(outboundVO).isSuccess();

        return deleteOrder && deleteOutbound;
    }

    /**
     * no+productId+repositoryId 不存在，新增订单，新增出库
     *
     * @param orderVO
     * @return
     */
    @Transactional
    public boolean addOrder(OrderVO orderVO) {
        // 新增订单
        boolean saveOrder = save(MyBeanUtils.copy(orderVO, Order.class));
        // 新增出库
        OutboundVO outboundVO = MyBeanUtils.copy(orderVO, OutboundVO.class)
                .setNo(orderVO.getNo())
                .setTypeId(InOutTypeEnum.SALE_OUT.getId());
        boolean saveOutbound = outboundService.addOne(outboundVO).isSuccess();

        return saveOrder && saveOutbound;


    }

    /**
     * 订单补发
     * isAddNum：0 换单号发货，拼接快递单号
     * isAddNum：1 补发，拼接快递单号+新增出库
     *
     * @param oldOrder
     * @param orderVO
     */
    @Transactional
    public boolean reissueOrder(Order oldOrder, OrderVO orderVO) {
        // 拼接快递单号
        String expressNum = DataUtils.concatString(oldOrder.getExpressNum(), orderVO.getExpressNum());
        oldOrder.setExpressNum(expressNum);

        // 不叠加，只拼接快递单号
        if (orderVO.getIsAddNum() == 0) {
            return updateById(oldOrder);
        }

        // 数量叠加，拼接快递单号+修改数量+新增出库
        oldOrder.setActualNum(oldOrder.getActualNum() + orderVO.getActualNum());
        oldOrder.setIsFinish(oldOrder.getPlanNum() > oldOrder.getActualNum() ? 0 : 1);
        boolean saveOrder = updateById(oldOrder);

        // 新增出库
        OutboundVO outboundVO = MyBeanUtils.copy(orderVO, OutboundVO.class)
                .setTypeId(InOutTypeEnum.SALE_OUT.getId());
        boolean saveOutbound = outboundService.addOne(outboundVO).isSuccess();
        return saveOrder && saveOutbound;
    }

    //============================================私有方法开始============================================


    //============================================私有方法结束============================================
}






